﻿using AIClient.Configs;
using AIClient.Utils;
using NetMsg.Card;
using System;
using System.Collections.Generic;
using System.Linq;
using Extensions;

namespace AIClient.Players.Module.Card
{
    public partial class BattleField
    {
        private (int Card, int Pos) PutData;

        /* AI行为树(修改时务必关闭掉Reshaper强制换行(options->C#->fmtStyle->warp long lines),不然树构造的代码格式会很乱,不要用Reshaper的CleanCode)
         * 实现: 进入回合是启动AI计时器,AI每隔period时间执行一遍行为树,如果执行结果是Failed,则执行完毕后会
         * 结束回合,否则AI计时器会继续执行直到行为树结果Failed
         * root ->& 报名
         *      ->& 等待匹配成功
         *      ->& 回合操作
         *          ->| 第一回合
         *              -> 第一回合出卡逻辑
         *          ->| 非第一回合
         *              -> 正常出卡逻辑
         *              
         * 出卡逻辑 -> 我方水晶为空
         *              -> 考并上阵保护水晶
         *          -> 可以快攻
         *              -> 思考并快攻
         *          -> 我方需要补位
         *              -> 思考并补位
         *          -> 我方替换后援
         *              -> 思考并替换
         */

        private BehaviourTree CreateCardBehaviourTree()
        {
            // 先手回合
            var firstTurn = new SequenceNode()
                           .AddChild(new ConditionNode(() => _offensive == _player.PlayerId))
                           .AddChild(new ConditionNode(() => _turnCount == 1))
                           .AddChild(CreateOffenTurnAction());

            return new BehaviourTree(new SelectNode() /*.AddChild(firstTurn)*/.AddChild(CreateNormalTurnAction()));
        }

        // AI先手第一回合行动
        private BTNode CreateOffenTurnAction()
        {
            /* root ->& 放第一张卡
             *              ->| 放优先卡
             *                      ->& 有优先卡
             *                      ->& 放优先卡
             *              ->| 放龙蛋卡
             *      ->& 放第二张卡
             *      ->& 放第三张卡
             *              ->| 放优先卡
             *                      ->& 有优先卡
             *                      ->& 放优先卡
             *              ->| 放龙胆卡
             *                      ->& 有指定龙蛋卡
             *                      ->& 放龙蛋卡
             */


            bool HasPreferCard()
            {
                PutData.Card = _hands.Find(card => _aiCfg.OffendsivePreferCards.Contains(card));
                return PutData.Card != 0;
            }

            bool IsSelfCardCountEqual(int count)
            {
                return _boardSelf.Count(card => card != null) == count;
            }


            void RandonSecondPos()
            {
                PutData.Pos = _aiCfg.OffenSecondPutPos[_aiCfg.OffenSecondPutPos.GetRandomIndex()];
            }

            return new SelectNode().AddChild(new SelectNode().AddChild(new SequenceNode().AddChild(new ConditionNode(() => IsSelfCardCountEqual(0)))
                                                                                         .AddChild(new ConditionNode(HasPreferCard))
                                                                                         .AddChild(CreateSetPosAction(_aiCfg.OffenFirstPutPos))
                                                                                         .AddChild(CreatePutCardAction()))
                                                             .AddChild(new SequenceNode().AddChild(new ConditionNode(() => IsSelfCardCountEqual(0)))
                                                                                         .AddChild(CreateSetCardAction(_aiCfg.IceElemEggId))
                                                                                         .AddChild(CreateSetPosAction(_aiCfg.OffenFirstPutPos))
                                                                                         .AddChild(CreatePutCardAction())))
                                   .AddChild(new SequenceNode().AddChild(new ConditionNode(() => IsSelfCardCountEqual(1)))
                                                               .AddChild(new ActionNode(RandonSecondPos))
                                                               .AddChild(CreateSetCardAction(_aiCfg.FireElemEggId))
                                                               .AddChild(CreatePutCardAction())) // 第二次放卡
                                   .AddChild(new SelectNode().AddChild(new SequenceNode().AddChild(new ConditionNode(() => IsSelfCardCountEqual(2)))
                                                                                         .AddChild(new ConditionNode(HasPreferCard))
                                                                                         .AddChild(CreateSetPosAction(_aiCfg.OffenThirdPutPos))
                                                                                         .AddChild(CreatePutCardAction()))
                                                             .AddChild(new SequenceNode().AddChild(new ConditionNode(() => IsSelfCardCountEqual(2)))
                                                                                         .AddChild(new ConditionNode(() => _hands.Contains(_aiCfg.IceElemEggId)))
                                                                                         .AddChild(CreateSetCardAction(_aiCfg.IceElemEggId))
                                                                                         .AddChild(CreateSetPosAction(_aiCfg.OffenThirdPutPos))
                                                                                         .AddChild(CreatePutCardAction())));
        }

        // 正常回合AI
        private BTNode CreateNormalTurnAction()
        {
            return new SelectNode()
                  .AddChild(CreateProtectCrystalAction())
                  .AddChild(CreateAttackAction())
                  .AddChild(CreateProtectLaneAction())
                  .AddChild(CreateReplaceAction())
                  .AddChild(CreateCastSkillAction());
        }

        // 保护水晶
        private BTNode CreateProtectCrystalAction()
        {
            /* root ->& 某个水晶Hp=0
             *      ->& 该列没有卡
             *      ->& 上场卡
             *          ->| 有第一梯队卡
             *          ->| 有先锋卡
             *          ->| 有后援卡
             */

            bool HasPreferCard()
            {
                PutData.Card = _hands.Find(hand => _aiCfg.ProtectCrystalPreferCard.Contains(hand));
                return PutData.Card != 0;
            }

            bool HasVangCard()
            {
                PutData.Card = GetCanPutHands().Find(hand => GetCardCfg(hand).CardType == CardType.Vanguard);
                return PutData.Card != 0;
            }

            bool HasGuardCard()
            {
                PutData.Card = GetCanPutHands().Find(hand => GetCardCfg(hand).CardType == CardType.Guard);
                return PutData.Card != 0;
            }

            // [[0,2,4][1,3,5]],可以保护说明此列是空的,2个位置都能放牌
            int GetPutPos()
            {
                var col = _crystalSelf.IndexOf(0);
                return GetCardCfg(PutData.Card).CardType == CardType.Vanguard ? _rowNum * col : _rowNum * col + 1;
            }

            var putCardAction = new SequenceNode().AddChild(new SelectNode().AddChild(new ConditionNode(HasPreferCard)) // 优先卡
                                                                            .AddChild(new ConditionNode(HasVangCard))   // 先锋卡
                                                                            .AddChild(new ConditionNode(HasGuardCard))) // 后援卡
                                                  .AddChild(new ConditionNode(() => PutData.Card != 0))
                                                  .AddChild(CreateSetPosByFuncAciton(GetPutPos))
                                                  .AddChild(CreatePutCardAction());
            return new SequenceNode().AddChild(new ConditionNode(() => _crystalSelf.Contains(0)))
                                     .AddChild(new ConditionNode(() => GetColCards(_crystalSelf.IndexOf(0)).Count == 0)) // 只能有1列水晶为0,2列为0时已经输了.
                                     .AddChild(putCardAction);
        }

        // 快攻
        private BTNode CreateAttackAction()
        {
            /* root ->& 满足快攻条件:1.对方某列没有卡卡 2.我方该列有位置
             *      ->& 上场卡
             *            ->| 第一梯队
             *            ->| 其他前锋
            */

            var attackCol = -1;

            bool IsFitAttack()
            {
                var nullCols = new List<int>();
                for (var i = 0; i < _colNum; ++i)
                {
                    var boardCards = GetColCards(i, false);
                    if (boardCards.Count != 0) continue;

                    nullCols.Add(i);
                }

                // 敌人没有空列
                if (nullCols.Count == 0) return false;

                var hasBoxCols = new List<int>();
                foreach (var index in nullCols)
                {
                    var boardCards = GetColCards(index);
                    if (boardCards.Count == _rowNum) continue; // 我方该列没位子

                    hasBoxCols.Add(index);
                }

                // 敌方空列对应的我方列没位置
                if (hasBoxCols.Count == 0) return false;

                attackCol = hasBoxCols[0];
                return true;
            }

            bool HasPerferCard()
            {
                PutData.Card = _hands.Find(hand => _aiCfg.AttackPreferCard.Contains(hand));
                return PutData.Card != 0;
            }

            bool HasVanGCard()
            {
                PutData.Card = 0;
                foreach (var hand in _hands)
                {
                    var cardCfg = GetCardCfg(hand);
                    if (cardCfg.CardType == CardType.Guard) continue;

                    if (cardCfg.Attack == 0) continue;

                    if (cardCfg.Power > _apNumSelf) continue;

                    if (PutData.Card == 0 || GetCardCfg(PutData.Card).Power > cardCfg.Power) // 优先行动点低的
                        PutData.Card = hand;
                }

                return PutData.Card != 0;
            }

            // 可以放牌说明col列必至少有一个位子
            int GetPutPos()
            {
                var perferPos = 0;
                switch (GetCardCfg(PutData.Card).CardType)
                {
                    case CardType.Vanguard:
                        perferPos = attackCol * _rowNum;
                        return _boardSelf[perferPos] == null ? perferPos : perferPos + 1;
                    default:
                        perferPos = attackCol * _rowNum + 1;
                        return _boardSelf[perferPos] == null ? perferPos : perferPos - 1;
                }
            }

            return new SequenceNode().AddChild(new ConditionNode(IsFitAttack))
                                     .AddChild(new SequenceNode().AddChild(new SelectNode().AddChild(new ConditionNode(HasPerferCard))
                                                                                           .AddChild(new ConditionNode(HasVanGCard)))
                                                                 .AddChild(new ConditionNode(() => PutData.Card != 0))
                                                                 .AddChild(CreateSetPosByFuncAciton(GetPutPos))
                                                                 .AddChild(CreatePutCardAction()));
        }

        // 补位
        private BTNode CreateProtectLaneAction()
        {
            /* root ->& 满足保护列条件
             *          ->& 条件1:某列没有卡
             *          ->& 条件2
             *              ->| 3列水晶都满,场上卡数<2
             *              ->| 任意一列水晶<=2时,场上卡数<3
             *              ->| 任意一列水晶=0时,场上卡数<4
             *      ->& 上场卡
             */

            var col = -1;

            // 条件一
            bool HasNullCol()
            {
                for (var i = 0; i < _colNum; ++i)
                {
                    var cards = GetColCards(i);
                    if (cards.Count == 0)
                    {
                        col = i;
                        return true;
                    }
                }

                return false;
            }

            // 条件二的条件1
            bool CheckFitSelectCond1()
            {
                if (_crystalSelf.Exists(crystal => crystal < _crystalHpMax))
                    return false;

                return _boardSelf.Count(boardCard => boardCard != null) < 2;
            }

            // 条件二的条件2
            bool CheckFitSelectCond2()
            {
                if (_crystalSelf.TrueForAll(crystal => crystal == _crystalHpMax))
                    return false;

                return _boardSelf.Count(boardCard => boardCard != null) < 3;
            }

            // 条件二的条件3
            bool CheckFitSelectCond3()
            {
                if (!_crystalSelf.Exists(crystal => crystal == 0))
                    return false;

                return _boardSelf.Count(boardCard => boardCard != null) < 4;
            }

            // 第一梯队卡
            bool HasPreferCard()
            {
                PutData.Card = _hands.Find(hand => _aiCfg.ProtectLanePreferCards.Contains(hand));
                return PutData.Card != 0;
            }

            // 第二梯队卡
            bool HasLessPreferCard()
            {
                PutData.Card = _hands.Find(hand => GetCardCfg(hand).CardType == CardType.Guard);
                return PutData.Card != 0;
            }

            // 第三梯队卡
            bool HasLikeCard()
            {
                PutData.Card = _hands.Find(hand => _aiCfg.ProtectLaneLikeCards.Contains(hand));
                return PutData.Card != 0;
            }

            // 第四梯队卡
            bool HasLessLikeCard()
            {
                PutData.Card = _hands.Find(hand => GetCardCfg(hand).CardType == 0);
                return PutData.Card != 0;
            }

            int GetPutPos()
            {
                return col * _rowNum + (int) GetCardCfg(PutData.Card).CardType;
            }

            return new SequenceNode().AddChild(new ConditionNode(HasNullCol))
                                     .AddChild(new SelectNode().AddChild(new ConditionNode(CheckFitSelectCond1))
                                                               .AddChild(new ConditionNode(CheckFitSelectCond2))
                                                               .AddChild(new ConditionNode(CheckFitSelectCond3)))
                                     .AddChild(new SelectNode().AddChild(new ConditionNode(HasPreferCard))
                                                               .AddChild(new ConditionNode(HasLessPreferCard))
                                                               .AddChild(new ConditionNode(HasLikeCard))
                                                               .AddChild(new ConditionNode(HasLessLikeCard)))
                                     .AddChild(new ConditionNode(() => PutData.Card != 0))
                                     .AddChild(CreateSetPosByFuncAciton(GetPutPos))
                                     .AddChild(CreatePutCardAction());
        }

        // 替换后援
        private BTNode CreateReplaceAction()
        {
            /* root ->& 场上有后援卡
             *      ->& 有可上场的后援卡
             *      ->& 上卡 
             */

            bool HasFitBoardGuard()
            {
                BoardCard target = null; // 替换目标
                PutData.Pos = -1;
                for (var i = 0; i < _boardSelf.Length; ++i)
                {
                    var boardCard = _boardSelf[i];
                    if (boardCard == null || boardCard.CardType == CardType.Vanguard) continue;

                    if (target == null)
                    {
                        target      = boardCard;
                        PutData.Pos = i;
                    }
                    else // 按照条件选择优先级高的
                    {
                        if (!target.IsMarked && boardCard.IsMarked)
                        {
                            target      = boardCard;
                            PutData.Pos = i;
                        }
                        else if (target.Cfg.Health - target.Health < target.Cfg.Health - boardCard.Health)
                        {
                            target      = boardCard;
                            PutData.Pos = i;
                        }
                        else if (target.Power >= boardCard.Power)
                        {
                            target      = boardCard;
                            PutData.Pos = i;
                        }
                    }
                }

                return PutData.Pos != -1;
            }

            bool HasFitHandGuard()
            {
                foreach (var hand in _hands)
                {
                    var card = GetCardCfg(hand);
                    if (card.CardType != CardType.Guard || card.Power > _apNumSelf) continue;

                    PutData.Card = hand;
                    return true;
                }

                return false;
            }

            return new SequenceNode().AddChild(new ConditionNode(HasFitBoardGuard))
                                     .AddChild(new ConditionNode(HasFitHandGuard))
                                     .AddChild(CreatePutCardAction());
        }

        // 每回合技能发动
        private BTNode CreateCastSkillAction()
        {
            /* root ->& 有带有我方回合技能的卡
             *      ->& 发动技能
             */

            bool HasSelfRoundSkill()
            {
                PutData.Card = 0;
                PutData.Pos  = -1;

                for (var i = 0; i < _boardSelf.Length; ++i)
                {
                    var boardCard = _boardSelf[i];
                    if (boardCard == null) continue;
                    if (boardCard.Cfg.SkillUseType != SkillUseType.Manual) continue;
                    if (boardCard.Cfg.SkillUseTime != SkillUseTime.SelfRound) continue;
                    if (!boardCard.HasSkill) continue;

                    PutData.Pos  = i;
                    PutData.Card = boardCard.Cfg.CardId;
                    break;
                }

                return PutData.Card != 0;
            }

            void OnCastSkillEnd()
            {
                _boardSelf[PutData.Pos].HasSkill = false;
            }

            return new SequenceNode().AddChild(new ConditionNode(HasSelfRoundSkill))
                                     .AddChild(new ActionNode(TryCastSkill))
                                     .AddChild(new ActionNode(OnCastSkillEnd));
        }

        private BTNode CreateSetCardAction(int cardId)
        {
            return new ActionNode(() => PutData.Card = cardId);
        }

        private BTNode CreateSetPosByFuncAciton(Func<int> getPosFunc)
        {
            return new ActionNode(() => PutData.Pos = getPosFunc.Invoke());
        }

        private BTNode CreateSetPosAction(int pos)
        {
            return new ActionNode(() => PutData.Pos = pos);
        }

        private BTNode CreatePutCardAction()
        {
            return new SequenceNode().AddChild(new ConditionNode(() => PutData.Card != 0))
                                     .AddChild(new ActionNode(PutCard))
                                     .AddChild(new ActionNode(TryCastSkill));
        }

        #region 卡牌技能

        // 每个卡牌技能
        private void TryCastSkill()
        {
            var args = new List<int>();
            switch (PutData.Card)
            {
                case 1: // 冰淇淋
                    {
                        // 我方血量低于初始值中差距最大的
                        var target = _boardSelf.Where(card => card != null && card.Health < card.Cfg.Health)
                                               .OrderByDescending(card => card, HealthDiffAsec.Comparer)
                                               .FirstOrDefault();
                        if (target != null)
                        {
                            args.Add(GetAppointTargetArg(true));
                            args.Add(Array.IndexOf(_boardSelf, target));
                            break;
                        }

                        // 敌方攻击力低于初始值中差距最大的
                        target = _boardEnemy.Where(card => card != null && card.Attack < card.Cfg.Attack)
                                            .OrderByDescending(card => card, AttackDiffAsec.Comparer)
                                            .FirstOrDefault();
                        if (target == null) return;

                        args.Add(GetAppointTargetArg(false));
                        args.Add(Array.IndexOf(_boardEnemy, target));
                        break;
                    }
                case 2: // 再生
                    {
                        // 敌方攻击高于初始值中差距最大的
                        var target = _boardEnemy.Where(card => card != null && card.Attack > card.Cfg.Attack)
                                                .OrderBy(card => card, AttackDiffAsec.Comparer)
                                                .FirstOrDefault();
                        if (target != null)
                        {
                            args.Add(GetAppointTargetArg(false));
                            args.Add(Array.IndexOf(_boardEnemy, target));
                            break;
                        }

                        // 敌方生命高于初始值中差距最大的
                        target = _boardEnemy.Where(card => card != null && card.Health > card.Cfg.Health)
                                            .OrderBy(card => card, HealthDiffAsec.Comparer)
                                            .FirstOrDefault();
                        if (target != null)
                        {
                            args.Add(GetAppointTargetArg(false));
                            args.Add(Array.IndexOf(_boardEnemy, target));
                            break;
                        }

                        // 我方攻击低于初始值中差距最大的
                        target = _boardSelf.Where(card => card != null && card.Attack < card.Cfg.Attack)
                                           .OrderByDescending(card => card, AttackDiffAsec.Comparer)
                                           .FirstOrDefault();
                        if (target != null)
                        {
                            args.Add(GetAppointTargetArg(true));
                            args.Add(Array.IndexOf(_boardSelf, target));
                            break;
                        }

                        // 我方生命低于初始值中差距最大的
                        target = _boardSelf.Where(card => card != null && card.Health < card.Cfg.Health)
                                           .OrderByDescending(card => card, HealthDiffAsec.Comparer)
                                           .FirstOrDefault();
                        if (target == null) return;

                        args.Add(GetAppointTargetArg(true));
                        args.Add(Array.IndexOf(_boardSelf, target));
                        break;
                    }
                case 3: // 零度光线
                    {
                        // 敌方未被标记的攻击最高的前锋卡
                        var target = _boardEnemy.Where(card => card != null && !card.IsMarked && card.CardType == 0)
                                                .OrderByDescending(card => card.Attack)
                                                .FirstOrDefault();
                        if (target != null)
                        {
                            args.Add(GetAppointTargetArg(false));
                            args.Add(Array.IndexOf(_boardEnemy, target));
                            break;
                        }

                        // 敌方未被标记的生命最高后援卡
                        target = _boardEnemy
                                .Where(card => card != null && !card.IsMarked && card.CardType == CardType.Guard)
                                .OrderByDescending(card => card.Health)
                                .FirstOrDefault();
                        if (target == null) return;

                        args.Add(GetAppointTargetArg(false));
                        args.Add(Array.IndexOf(_boardEnemy, target));
                        break;
                    }
                case 4: // 神枪手
                    {
                        // 敌方生命最低的后援卡
                        var target = _boardEnemy.Where(card => card != null && card.CardType == CardType.Guard)
                                                .OrderBy(card => card.Health)
                                                .FirstOrDefault();
                        if (target != null)
                        {
                            args.Add(GetAppointTargetArg(false));
                            args.Add(Array.IndexOf(_boardEnemy, target));
                            break;
                        }

                        // 敌方生命最低的前锋卡
                        target = _boardEnemy.Where(card => card != null && card.CardType == 0)
                                            .OrderBy(card => card.Health)
                                            .FirstOrDefault();
                        if (target == null) return;

                        args.Add(GetAppointTargetArg(false));
                        args.Add(Array.IndexOf(_boardEnemy, target));
                        break;
                    }
                case 8: // 破坏剑
                    {
                        // 随机带"死亡"前缀的卡
                        var target = _boardEnemy.FirstOrDefault(card => card != null && !card.IsMarked && card.Cfg.SkillUseTime == SkillUseTime.Death);
                        if (target != null)
                        {
                            args.Add(GetAppointTargetArg(false));
                            args.Add(Array.IndexOf(_boardEnemy, target));
                            break;
                        }

                        // 随机带"每回合"前缀的卡
                        target = _boardEnemy.FirstOrDefault(card => card != null && !card.IsMarked && card.Cfg.SkillUseTime == SkillUseTime.EachRound);
                        if (target != null)
                        {
                            args.Add(GetAppointTargetArg(false));
                            args.Add(Array.IndexOf(_boardEnemy, target));
                            break;
                        }

                        // 随机选一张卡
                        target = _boardEnemy.FirstOrDefault(card => card != null && !card.IsMarked);
                        if (target == null) return;

                        args.Add(GetAppointTargetArg(false));
                        args.Add(Array.IndexOf(_boardEnemy, target));
                        break;
                    }
                case 10: // 死亡预言
                    {
                        // 敌方生命最高的前锋卡
                        var target = _boardEnemy.Where(card => card != null && !card.IsMarked && card.CardType == 0)
                                                .OrderByDescending(card => card.Health)
                                                .FirstOrDefault();
                        if (target != null)
                        {
                            args.Add(GetAppointTargetArg(false));
                            args.Add(Array.IndexOf(_boardEnemy, target));
                            break;
                        }

                        // 敌方生命最高的后援卡
                        target = _boardEnemy.Where(card => card != null && !card.IsMarked && card.CardType == CardType.Guard)
                                            .OrderByDescending(card => card.Health)
                                            .FirstOrDefault();
                        if (target == null) return;

                        args.Add(GetAppointTargetArg(false));
                        args.Add(Array.IndexOf(_boardEnemy, target));
                        break;
                    }
                case 12: // 灵魂献祭
                    {
                        // 牺牲卡牌:我方行动点最低的卡,优先前锋卡
                        var target = _boardSelf.Where(card => card != null)
                                               .OrderBy(card => card.CardType)
                                               .ThenBy(card => card.Power)
                                               .FirstOrDefault();
                        if (target == null) return;

                        args.Add(GetAppointTargetArg(true));
                        args.Add(Array.IndexOf(_boardSelf, target));

                        // 作用卡:敌方行动点最高,优先后援
                        target = _boardEnemy.Where(card => card != null)
                                            .OrderByDescending(card => card)
                                            .ThenByDescending(card => card.Power)
                                            .FirstOrDefault();
                        if (target == null) return;

                        args.Add(GetAppointTargetArg(false));
                        args.Add(Array.IndexOf(_boardSelf, target));
                        break;
                    }
                case 14: // 时光倒流
                    {
                        // 行动点最高,优先前锋卡
                        var target = _boardSelf.Where(card => card != null)
                                               .OrderBy(card => card.CardType)
                                               .ThenByDescending(card => card.Power)
                                               .FirstOrDefault();
                        if (target != null)
                        {
                            args.Add(GetAppointTargetArg(true));
                            args.Add(Array.IndexOf(_boardSelf, target));
                            break;
                        }

                        // 行动点低,优先后援卡
                        target = _boardSelf.Where(card => card != null)
                                           .OrderByDescending(card => card.CardType)
                                           .ThenBy(card => card.Power)
                                           .FirstOrDefault();

                        if (target == null) return;

                        args.Add(GetAppointTargetArg(true));
                        args.Add(Array.IndexOf(_boardSelf, target));
                        break;
                    }
                case 15: // 因果颠倒
                    {
                        var target = _boardEnemy.Where(card => card != null)
                                                .OrderBy(card => card.Power)
                                                .FirstOrDefault();

                        if (target == null) return;

                        args.Add(GetAppointTargetArg(false));
                        args.Add(Array.IndexOf(_boardEnemy, target));
                        break;
                    }
                case 17: // 灭世
                    {
                        var col = _crystalEnemy.IndexOf(_crystalEnemy.Min());
                        args.Add(GetAppointTargetArg(false));
                        args.Add(col);
                    }
                    break;
                case 20: // 奔雷拳
                    {
                        var colCardsCount = new List<int>();
                        for (var i = 0; i < _colNum; ++i)
                            colCardsCount.Add(GetColCards(i, false).Count);

                        var maxNum = colCardsCount.Count;
                        if (maxNum == 0) return;

                        var col = colCardsCount.IndexOf(maxNum);
                        args.Add(GetAppointTargetArg(false));
                        args.Add(col);
                    }
                    break;
                case 21: // K.O
                    {
                        // 行动点最高的后援卡
                        var target = _boardEnemy.Where(card => card != null && card.CardType == CardType.Guard)
                                                .OrderByDescending(card => card.Power)
                                                .FirstOrDefault();
                        if (target == null) return;

                        args.Add(GetAppointTargetArg(false));
                        args.Add(Array.IndexOf(_boardEnemy, target));
                        break;
                    }
                case 22: // 毒原体
                    {
                        var target = _boardSelf.Where(card => card != null && card.Health > 1)
                                               .OrderByDescending(card => card.Health)
                                               .FirstOrDefault();

                        if (target == null) return;

                        args.Add(GetAppointTargetArg(true));
                        args.Add(Array.IndexOf(_boardSelf, target));
                        break;
                    }
                case 23: // 生化改造
                    {
                        // 攻击力最低前锋卡
                        var target = _boardEnemy.Where(card => card != null && card.Attack > 0 && card.CardType == 0)
                                                .OrderBy(card => card.Attack)
                                                .FirstOrDefault();
                        if (target != null)
                        {
                            args.Add(GetAppointTargetArg(false));
                            args.Add(Array.IndexOf(_boardEnemy, target));
                            break;
                        }

                        // 攻击力最低的后援卡
                        target = _boardEnemy.Where(card => card != null && card.Attack > 0 && card.CardType == CardType.Guard)
                                            .OrderBy(card => card.Attack)
                                            .FirstOrDefault();
                        if (target == null) return;

                        args.Add(GetAppointTargetArg(false));
                        args.Add(Array.IndexOf(_boardEnemy, target));
                        break;
                    }

                case 24: // 毒霾
                    {
                        var colCardsCount = new List<int>();
                        for (var i = 0; i < _colNum; ++i)
                            colCardsCount.Add(GetColCards(i, false).Count(card => !card.IsMarked));
                        var max = colCardsCount.Max();
                        if (max == 0) return;

                        var col = colCardsCount.IndexOf(max);
                        args.Add(GetAppointTargetArg(false));
                        args.Add(col);
                        break;
                    }
                case 27: // 激流葬
                    {
                        // 后援卡,生命值 <=2,优先hp最低的
                        var target = _boardEnemy
                                    .Where(card => card != null && card.CardType == CardType.Guard && card.Health <= 2)
                                    .OrderBy(card => card.Health)
                                    .FirstOrDefault();
                        if (target != null)
                        {
                            args.Add(GetAppointTargetArg(false));
                            args.Add(Array.IndexOf(_boardEnemy, target));
                            break;
                        }

                        // 前锋卡,生命 <=2,优先hp最高的
                        target = _boardEnemy.Where(card => card != null && card.CardType == 0 && card.Health <= 2)
                                            .OrderByDescending(card => card.Health)
                                            .FirstOrDefault();
                        if (target != null)
                        {
                            args.Add(GetAppointTargetArg(false));
                            args.Add(Array.IndexOf(_boardEnemy, target));
                            break;
                        }

                        // 任意卡
                        target = _boardEnemy.FirstOrDefault(card => card != null);
                        if (target == null) return;

                        args.Add(GetAppointTargetArg(false));
                        args.Add(Array.IndexOf(_boardEnemy, target));
                        break;
                    }
                case 30: // 熔岩巨炮
                    {
                        var col = PutData.Pos / _rowNum;

                        // 后援卡,生命<=2
                        var target = GetColCards(col, false)
                           .FirstOrDefault(card => card != null && card.CardType == CardType.Guard && card.Health <= 2);
                        if (target != null)
                        {
                            args.Add(GetAppointTargetArg(false));
                            args.Add(Array.IndexOf(_boardEnemy, target));
                            break;
                        }

                        // 随机卡
                        target = GetColCards(col, false).FirstOrDefault();

                        if (target == null) return;

                        args.Add(GetAppointTargetArg(false));
                        args.Add(Array.IndexOf(_boardEnemy, target));
                        break;
                    }
                case 32: // 雷锋波
                    {
                        var target = _boardEnemy.Where(card => card != null && !card.IsMarked)
                                                .OrderByDescending(card => card.CardType)
                                                .ThenByDescending(card => card.Health)
                                                .FirstOrDefault();
                        if (target == null) return;

                        args.Add(GetAppointTargetArg(false));
                        args.Add(Array.IndexOf(_boardEnemy, target));
                        break;
                    }
                case 33: // 雷劫
                    {
                        // 前锋卡,未标记,hp最高优先
                        var target = _boardEnemy.Where(card => card != null && !card.IsMarked)
                                                .OrderByDescending(card => card.Health)
                                                .FirstOrDefault();
                        if (target != null)
                        {
                            args.Add(GetAppointTargetArg(false));
                            args.Add(Array.IndexOf(_boardEnemy, target));
                            break;
                        }

                        // 后援卡,未标记,power最高优先
                        target = _boardEnemy.Where(card => card != null && !card.IsMarked)
                                            .OrderByDescending(card => card.Power)
                                            .FirstOrDefault();
                        if (target == null) return;

                        args.Add(GetAppointTargetArg(false));
                        args.Add(Array.IndexOf(_boardEnemy, target));
                        break;
                    }
                case 39: // 冰元素掌控者
                    {
                        // 先锋卡,未标记,hp高优先
                        var target = _boardEnemy.Where(card => card != null && !card.IsMarked && card.CardType == 0)
                                                .OrderByDescending(card => card.Health)
                                                .FirstOrDefault();
                        if (target != null)
                        {
                            args.Add(GetAppointTargetArg(false));
                            args.Add(Array.IndexOf(_boardEnemy, target));
                            break;
                        }

                        // 后援卡,未标记,ak高优先
                        target = _boardEnemy.Where(card => card != null && !card.IsMarked && card.CardType == CardType.Guard)
                                            .OrderByDescending(card => card.Attack)
                                            .FirstOrDefault();
                        if (target == null) return;

                        args.Add(GetAppointTargetArg(false));
                        args.Add(Array.IndexOf(_boardEnemy, target));
                        break;
                    }

                case 40: // 自爆
                    {
                        // 生命低的任意卡
                        var target = _boardEnemy.Where(card => card != null)
                                                .OrderBy(card => card.Health)
                                                .FirstOrDefault();
                        if (target == null) return;

                        args.Add(GetAppointTargetArg(false));
                        args.Add(Array.IndexOf(_boardEnemy, target));
                        break;
                    }
                case 42: // 火元素掌控者
                    {
                        // 前锋卡,未标记,低生命
                        var target = _boardEnemy.Where(card => card != null && !card.IsMarked && card.CardType == 0)
                                                .OrderBy(card => card.Health)
                                                .FirstOrDefault();
                        if (target != null)
                        {
                            args.Add(GetAppointTargetArg(false));
                            args.Add(Array.IndexOf(_boardEnemy, target));
                            break;
                        }

                        // 后援卡,未标记,低生命优先
                        target = _boardEnemy.Where(card => card != null && !card.IsMarked && card.CardType == CardType.Guard)
                                            .OrderBy(card => card.Health)
                                            .FirstOrDefault();
                        if (target == null) return;

                        args.Add(GetAppointTargetArg(false));
                        args.Add(Array.IndexOf(_boardEnemy, target));
                        break;
                    }
                case 46: // 青霾毒素
                    {
                        // 未标记,我方回合,优先前锋
                        var target = _boardEnemy.Where(card => card != null && !card.IsMarked && card.Cfg.SkillUseTime == SkillUseTime.SelfRound)
                                                .OrderBy(card => card.CardType)
                                                .FirstOrDefault();
                        if (target == null) return;

                        args.Add(GetAppointTargetArg(false));
                        args.Add(Array.IndexOf(_boardEnemy, target));
                        break;
                    }
                case 48: // 毒元素掌控者
                    {
                        // 后援,优先行动点低
                        var target = _boardEnemy.Where(card => card != null && card.CardType == CardType.Guard)
                                                .OrderBy(card => card.Power)
                                                .FirstOrDefault();
                        if (target == null) return;

                        args.Add(GetAppointTargetArg(false));
                        args.Add(Array.IndexOf(_boardEnemy, target));
                        break;
                    }
                case 49: // 冰结界龙
                    {
                        // 攻击力为0的卡
                        var target = _boardSelf.Where(card => card != null && card.Attack == 0)
                                               .OrderBy(card => card.CardType)
                                               .FirstOrDefault();
                        if (target == null) return;

                        args.Add(GetAppointTargetArg(true));
                        args.Add(Array.IndexOf(_boardSelf, target));
                        break;
                    }
                case 50: // 黑暗星耀龙
                    {
                        // 低hp优先
                        var target = _boardEnemy.Where(card => card != null)
                                                .OrderBy(card => card.Health)
                                                .FirstOrDefault();
                        if (target == null) return;

                        args.Add(GetAppointTargetArg(false));
                        args.Add(Array.IndexOf(_boardEnemy, target));
                        break;
                    }
                case 51: // 次元龙
                    {
                        //攻击1的卡,未标记
                        var target = _boardSelf.Where(card => card != null && !card.IsMarked && card.Attack == 1)
                                               .OrderBy(card => card.Power)
                                               .FirstOrDefault();
                        if (target == null) return;

                        args.Add(GetAppointTargetArg(true));
                        args.Add(Array.IndexOf(_boardSelf, target));
                        break;
                    }
                case 55: // 冰封结界
                    {
                        // 后援卡,行动点高优先
                        var target = _boardEnemy
                                    .Where(card => card != null && !card.IsMarked && card.CardType == CardType.Guard)
                                    .OrderByDescending(card => card.Power)
                                    .FirstOrDefault();
                        if (target == null) return;

                        args.Add(GetAppointTargetArg(false));
                        args.Add(Array.IndexOf(_boardEnemy, target));
                        break;
                    }
                case 57: // 次元领域
                    {
                        // 随机空位
                        var target = _boardEnemy.FirstOrDefault(card => card == null);
                        if (target == null) return;

                        args.Add(GetAppointTargetArg(false));
                        args.Add(Array.IndexOf(_boardEnemy, target));
                        break;
                    }

                default:
                    return;
            }
#if DEBUG
            if (args.Count == 0)
                Logger.LogError("释放一个没有选择参数的技能");
            if (args.Count % 2 != 0)
                Logger.LogError("选择参数必须是偶数个");
#endif
            if (args.Count == 0 || args.Count % 2 != 0) return;

            var useTime = GetCardCfg(PutData.Card).SkillUseTime == SkillUseTime.Admission ? UseSKillTime.Admission : UseSKillTime.SelfRound;
            UseSkill(PutData.Pos, useTime, args);
        }

        #endregion

        // 生命差值(生命小于初始值:差值升序,生命大于初始值:差值降序)
        private class HealthDiffAsec : IComparer<BoardCard>
        {
            public static HealthDiffAsec Comparer = new HealthDiffAsec();

            public int Compare(BoardCard x, BoardCard y)
            {
                return (x.Cfg.Health - x.Health) - (y.Cfg.Health - y.Health);
            }
        }

        // 攻击差值(攻击小于初始值:差值升序,攻击大于初始值:差值降序)
        private class AttackDiffAsec : IComparer<BoardCard>
        {
            public static AttackDiffAsec Comparer = new AttackDiffAsec();

            public int Compare(BoardCard x, BoardCard y)
            {
                return (x.Cfg.Attack - x.Attack) - (y.Cfg.Attack - y.Attack);
            }
        }

#if DEBUG
        private BTNode CreateDebugNode(string output = null)
        {
            var msg = output ?? $"putdata: card={PutData.Card} pos={PutData.Pos}";
            return new ActionNode(() => Console.WriteLine(output));
        }
#endif
    }
}